'''
Copyright (c) 2010, 2011 MIEM (http://miem.edu.ru/)
 
Authors:
    * Andrey Shtykovskiy    ( ashty@itas.miem.edu.ru      )
    * Edward Klyshinsky     ( klyshinsky@itas.miem.edu.ru )
    * Sergey R. Tumkovsky   ( srt@itas.miem.edu.ru        )
 
This file is part of MOAN (morphology analysis) software.
 
MOAN is free software: you can redistribute it and/or modify it 
under the terms of the GNU General Public License as published 
by the Free Software Foundation, either version 3 of the License, 
or (at your option) any later version.
 
This software is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU General Public License 
along with MOAN. If not, see http://www.gnu.org/licenses/.
'''
from yaml import YAMLError
import yaml

import math

from mcl_error import MCLParseError, MCLDocumentError

class Parser(object):
    ''' Parameters parser and dictionary compiler.
        
        This is only a draft, will be rewritten in future.
    '''
    def __init__(self):
        self.__documents = None
        self.__compilation_steps = list()
    
    def load(self, name):
        
        document = None
        stream = file(name, 'r')
        
        try:
            document = yaml.load(stream)
        except YAMLError:
            raise MCLParseError('invalid input document: ' + name)
        
        self.__documents = self.__select('documents', document)
        self.__compilation_steps = self.__select('compilation steps', document)
    
    def proceed(self):
        
        for record in self.__compilation_steps:
            if not record[0] is None:
                self.__process_record(record[0], record[1])
        
        for record in self.__documents["dictionary"]:
            if record[0] == "acronyms":
                self.__document_acronyms = record[1] 
    
    def __select(self, section_name, document):
        
        for record in document:
            if section_name == record:
                return document[record]
    
    def __count_bits(self, container):
        item_count = len(container)
        bit_states = item_count + int(math.ceil(item_count % 2))
        return int(bit_states/2)
    
    def __process_record(self, action, args):
        
        values = {'enumerate'       : self.__enumerate,
                  'enumerate with'  : self.__enumerate_with}
        
        values.get(action, lambda args: None)(args)
        
    def __enumerate(self, args):
        
        config = self.__select(args[0], self.__documents)
        start_index = args[1]
        
        if config is None:
            raise MCLParseError('enumerate: document ' + args[0] + ' not found')
        
        input_name = config[0][1]  # this should be fixed later
        output_name = config[1][1] # this should be fixed later
        
        try: 
            input_document = yaml.load(file(input_name, 'r'))
        except YAMLError:
            raise MCLParseError('error while parsing:' + input_name)
        
        output_document = dict()
        
        for record in input_document:
            
            current_index = start_index
            document_item = dict()
            
            for record_item in record[1]:
                document_item[record_item] = current_index
                current_index = current_index + 1
                
            output_document[record[0]] = [self.__count_bits(document_item), document_item]
                
        yaml.dump(output_document, file(output_name, 'w'))
        setattr(self, '__document_'+args[0], output_document)
        
    def get(self, name):
        document_name = "__document_" + name
        return getattr(self, document_name) 
        
    def __enumerate_with(self, args):
        
        output_document = dict()
        
        enumerator_document_name = '__document_'+args[2]
        start_index = args[1]
        
        try:
            enumerator_set = getattr(self, enumerator_document_name)
        except AttributeError:
            raise MCLDocumentError('document not found: self.__document_' + args[1])
        
        config = self.__select(args[0], self.__documents)
        
        input_name = config[0][1]
        output_name = config[1][1]
        
        try:
            input_document = yaml.load(file(input_name, 'r'))
        except YAMLError:
            raise MCLParseError('error while parsing:' + input_name)
        
        for item in input_document:
            item_name = item[0]
            item_set = item[1]
            
            current_index = start_index
            
            subdocument = dict()
            
            if len(item_set) == 0:
                continue
            
            for item in item_set:
                
                '''@todo: add a check for item presence here '''
                subdocument[item] = current_index
                
                bits = enumerator_set[item][0]
                current_index += bits
        
            output_document[item_name] = [current_index, subdocument]
        
        yaml.dump(output_document, file(output_name, 'w'))
        setattr(self, '__document_'+args[0], output_document)
        
        
